﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Enlightener.Engine.Structs__Enums___Interfaces;
using Enlightener.Engine.Utils;
using Mono.Cecil;
using Mono.Cecil.Cil;

namespace Enlightener.Engine.Deobfuscator.Tasks.Common
{
    public class AssemblyStripper : DeobfuscationTask
    {
        public AssemblyStripper(AssemblyDefinition asmDef)
            : base(asmDef)
        {
        }

        [DeobfuscationPhase(1, "Strip assembly from bad members")]
        public static bool Phase1()
        {
            var tmp = new MarkedMember();
            try
            {
                foreach (var member in DeobfuscatorContext.MarkedMembers)
                {
                    switch (member.Type)
                    {
                        case MemberType.Type:
                            AsmDef.MainModule.Types.Remove(member.Member as TypeDefinition);
                            break;

                        case MemberType.Method:
                            (member.Member as MethodDefinition).DeclaringType.Methods.Remove(
                                member.Member as MethodDefinition);
                            break;

                        case MemberType.Field:
                            (member.Member as FieldDefinition).DeclaringType.Fields.Remove(
                                member.Member as FieldDefinition);
                            break;

                        case MemberType.Property:
                            (member.Member as PropertyDefinition).DeclaringType.Properties.Remove(
                                member.Member as PropertyDefinition);
                            break;

                        case MemberType.Resource:
                            AsmDef.MainModule.Resources.Remove(member.Member as EmbeddedResource);
                            break;

                        case MemberType.Attribute:
                            (member.ParentMember as ModuleDefinition).CustomAttributes.Remove(
                                member.Member as CustomAttribute);
                            break;

                        case MemberType.Instruction:
                            (member.ParentMember as MethodDefinition).Body.Instructions.Remove(
                                member.Member as Instruction);
                            break;
                    }

                    tmp = member;
                }
            }
            catch (Exception e)
            {
                if (tmp == null)
                    return true;

                PhaseError = new PhaseError
                {
                    Level = PhaseError.ErrorLevel.Minor,
                    Message = "Failed to clean up member!"
                };
            }

            Logger.VSLog(string.Format("{0} members cleaned from assembly...", DeobfuscatorContext.MarkedMembers.Count));
            return true;
        }
    }
}
